package org.summer.lawyer.pay.client.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.summer.lawyer.constant.enums.PaymentMethod;
import org.summer.lawyer.domain.vo.paychannel.PayChannelVo;
import org.summer.lawyer.pay.client.PayClient;
import org.summer.lawyer.pay.client.PayClientFactory;
import org.summer.lawyer.pay.client.impl.wechat.WeChatMiniAppPayClient;

import java.util.Map;
import java.util.concurrent.ConcurrentMap;

/**
 *
 */
@Slf4j
@Service
public class PayClientFactoryImpl implements PayClientFactory {

    /**
     * 支付客户端 Map
     *
     */
    private final ConcurrentMap<Long, AbstractPayClient> clients = MapUtil.newConcurrentHashMap();

    private final Map<PaymentMethod, Class<?>> clientClasses = MapUtil.newConcurrentHashMap();

    public PayClientFactoryImpl(){
        clientClasses.put(PaymentMethod.WECHAT_MINIAPP, WeChatMiniAppPayClient.class);
    }

    @Override
    public PayClient getPayClient(Long channelId) {
        AbstractPayClient client = clients.get(channelId);
        if(ObjectUtil.isNull(client)){
            log.error("[getPayClient]客户端({}) 未找到", channelId);
        }
        return client;
    }

    @Override
    public void createOrUpdatePayClient(PayChannelVo vo) {
            AbstractPayClient client = (AbstractPayClient) clients.get(vo.getId());
            if(ObjectUtil.isNull(client)){
                client = this.createPayClient(vo);
                client.init();
                clients.put(client.getId(), client);
            }else {
                client.refresh(vo);
            }
    }

    public AbstractPayClient createPayClient(PayChannelVo vo) {
        PaymentMethod paymentMethod = PaymentMethod.getByCode(vo.getChannelCode());
        Assert.notNull(paymentMethod, StrUtil.format("支付通道({}) 为空",vo.getChannelCode()));
        Class<?> payClientClass = clientClasses.get(paymentMethod);
        Assert.notNull(payClientClass, StrUtil.format("支付通道({}) Class 为空", vo.getChannelCode()));
        return (AbstractPayClient) ReflectUtil.newInstance(payClientClass, vo);
    }

    @Override
    public void registerPayClient(PaymentMethod paymentMethod, Class<?> payClientClass) {
            clientClasses.put(paymentMethod, payClientClass);
    }

//    public void removePayClient(PayChannelVo vo){
//        PaymentMethod paymentMethod = PaymentMethod.getByCode(vo.getChannelCode());
//    }
}
